Private Service Connectを使用して、EC2からBigQueryにVPN経由でアクセスする方法 (Part1: 環境準備編)
データアナリティクス事業本部の笠原です。
AWSとGCPをVPN接続して、EC2からBigQueryへアクセスする方法を試してみました。
以下、3つの記事に分けて掲載いたします。
- 環境準備編 (この記事)
- VPN構築編
- PSC/DNS設定編
この記事では、VPN構築する前に準備する、今回の検証用環境について説明します。 VPC/サブネットや仮想マシンを用意する内容ですので、すでに知っているという方は読み飛ばしていただいて構いません。
構成内容
最終的には以下のような構成になります。
AWSからGCPへVPN経由で接続し、Private Service ConnectエンドポイントからBigQueryへ接続します。
本記事では以下のような構成の検証用環境を準備したいと思います。
AWSとGCPにVPCとサブネットを構成し、各サブネットに仮想マシンを用意したいと思います。
GCPは接続確認用で使います。EC2 ⇒ BigQueryへのアクセスには不要になりますので、最終的には削除します。
また、EC2にBigQueryへアクセスする際に使用する bq
コマンドを使いたいので、Google Cloud SDKをEC2にインストールするのですが、インストール中にインターネットアクセスが必要です。方法はいくつか考えられますが、今回はNAT Gatewayを利用することで一時的にインターネットアクセスできるようにしたいと思います。NAT GatewayはGoogle Cloud SDKインストール後に削除します。
設定項目
AWS / GCP に分けて説明します。今回はAWS、GCPとも東京リージョンを使用します。
- AWS: ap-northeast-1
- GCP: asia-northeast1
また、AWSのVPCは 10.128.0.0/20
、privateサブネットは 10.128.1.0/24
とし、GCPのサブネットは 10.146.0.0/24
としました。
AWS設定
マネジメントコンソール上の操作内容は省略いたしますが、設定に使用したAWS CLIコマンドを掲載いたしますので、ご参考ください。
VPC
- VPC名: bigquery_vpn_test
- CIDR: 10.128.0.0/20
aws ec2 create-vpc --cidr-block 10.128.0.0/20 #=> VpcId: vpc-028bdb0ee3a9213b4 aws ec2 create-tags --resources vpc-028bdb0ee3a9213b4 --tags Key=Name,Value=bigquery_vpn_test
Subnet
EC2を配置するprivateサブネットを追加します。
- Subnet名: bigquery_vpn_test_private_subnet-1
- CIDR: 10.128.1.0/24
- アベイラビリティゾーン: ap-northeast-1d
aws ec2 create-subnet --vpc-id vpc-028bdb0ee3a9213b4 --cidr-block 10.128.1.0/24 --availability-zone ap-northeast-1d #=> SubnetId: subnet-03e945e9c28079b4f aws ec2 create-tags --resources subnet-03e945e9c28079b4f --tags Key=Name,Value=bigquery_vpn_test_private_subnet-1
NATゲートウェイ用のpublicサブネットも追加します。
- Subnet名: bigquery_vpn_test_public_subnet-1
- CIDR: 10.128.0.0/24
- アベイラビリティゾーン: ap-northeast-1a
aws ec2 create-subnet --vpc-id vpc-028bdb0ee3a9213b4 --cidr-block 10.128.0.0/24 --availability-zone ap-northeast-1a #=> SubnetId: subnet-054f3f50f4e3047e8 aws ec2 create-tags --resources subnet-054f3f50f4e3047e8 --tags Key=Name,Value=bigquery_vpn_test_public_subnet-1
サブネットをパブリックにする
publicサブネットにインターネットゲートウェイをアタッチしてルーティング設定します。
インターネットゲートウェイ生成
aws ec2 create-internet-gateway #=> InternetGatewayId: igw-097c7e4fe3ab80ee5
VPCにインターネットゲートウェイをアタッチ
aws ec2 attach-internet-gateway --vpc-id vpc-028bdb0ee3a9213b4 --internet-gateway-id igw-097c7e4fe3ab80ee5
VPCに対してカスタムルートテーブル作成
aws ec2 create-route-table --vpc-id vpc-028bdb0ee3a9213b4 #=> RouteTableId: rtb-0f51593375201bf25
インターネットゲートウェイへのすべてのトラフィック ( 0.0.0.0/0
) をポイントするルートを作成
aws ec2 create-route --route-table-id rtb-0f51593375201bf25 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-097c7e4fe3ab80ee5
publicサブネットに作成したカスタムルートテーブルを関連付け
aws ec2 associate-route-table --subnet-id subnet-054f3f50f4e3047e8 --route-table-id rtb-0f51593375201bf25
privateサブネット内にEC2起動
キーペアの作成 (キー名: gcp-vpn-test-kasahara
)
aws ec2 create-key-pair --key-name gcp-vpn-test-kasahara --query "KeyMaterial" --output text > gcp-vpn-test-kasahara.pem
カレントディレクトリにキーが出力されるので、 chmod
しておきます。
chmod 400 gcp-vpn-test-kasahara.pem
セキュリティグループの作成 (SG名: bigquery_vpn_test-sg
)
今回はセキュリティグループのルール追加は無しです。
aws ec2 create-security-group --group-name bigquery_vpn_test-sg --description "sg for bigquery_vpn_test" --vpc-id vpc-028bdb0ee3a9213b4 #=> GroupId: sg-039e68d4778071712
EC2を起動
- Amazon Linux 2 (x86-64) (image-id:
ami-0701e21c502689c31
) - インスタンスタイプ: t3a.micro
- プライベートサブネットに配置
- 先ほど作成したキーペアとセキュリティグループを指定
aws ec2 run-instances --image-id ami-0701e21c502689c31 --count 1 --instance-type t3a.micro --key-name gcp-vpn-test-kasahara --security-group-ids sg-039e68d4778071712 --subnet-id subnet-03e945e9c28079b4f #=> InstanceId: i-03c71fcc4ef8e6b20 aws ec2 create-tags --resources i-03c71fcc4ef8e6b20 --tags Key=Name,Value=bigquery_vpn_test
しばらくしてRunningになっているか確認します。
aws ec2 describe-instances --instance-id i-03c71fcc4ef8e6b20
SSM経由でEC2にSSHログインするための設定
プライベートサブネット上のEC2にSSM経由でログインするために以下の内容を実施してます。
- EC2にIAMロール付与
- SSM用VPCエンドポイント追加
今回はAWS CLIで実施してます。
SSM経由でEC2にSSHログインするために、IAMロールの付与
AWS管理ポリシーの中から、 AmazonEC2RoleforSSM
のARNを確認します。
aws iam list-policies --scope AWS --query "Policies[?PolicyName == 'AmazonEC2RoleforSSM']" #=> "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
以下のjsonドキュメントをカレントディレクトリ配下のjsonファイルに保存します。
今回は EC2AssumeRolePolicy.json
としました。
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } }
IAMロール作成 (ロール名: GcpVpnEc2SsmRole
)
aws iam create-role --role-name GcpVpnEc2SsmRole --assume-role-policy-document file://EC2AssumeRolePolicy.json
ロールに AmazonEC2RoleforSSM
ポリシーをアタッチします。
aws iam attach-role-policy --role-name GcpVpnEc2SsmRole --policy-arn "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
インスタンスプロファイル作成 (インスタンスプロファイル名: GcpVpnEc2SsmInstanceProfile
)
aws iam create-instance-profile --instance-profile-name GcpVpnEc2SsmInstanceProfile
プロファイルにロールを追加します。
aws iam add-role-to-instance-profile --instance-profile-name GcpVpnEc2SsmInstanceProfile --role-name GcpVpnEc2SsmRole
EC2にアタッチするために、一旦EC2を停止します。
aws ec2 stop-instances --instance-id i-03c71fcc4ef8e6b20
EC2にアタッチ
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=GcpVpnEc2SsmInstanceProfile --instance-id i-03c71fcc4ef8e6b20
SSM経由でEC2にSSHログインするために、SSM用のVPCエンドポイント追加
以下のページを参考にします。
エンドポイント用のセキュリティグループを作成 (SG名: bigquery_vpn_test-ssm-endpoint-sg
)
aws ec2 create-security-group --group-name bigquery_vpn_test-ssm-endpoint-sg --description "sg for ssm endpoint" --vpc-id vpc-028bdb0ee3a9213b4 #=> GroupId: sg-0f43c64ef09c225d7
EC2のSG (sg-039e68d4778071712
) をソースとして、 443
ポートを許可するルールを追加します。
aws ec2 authorize-security-group-ingress --group-id sg-0f43c64ef09c225d7 --protocol tcp --port 443 --source-group sg-039e68d4778071712
エンドポイントのサービス名を確認します。
aws ec2 describe-vpc-endpoint-services --query "ServiceDetails[?contains(ServiceName,\`ssm\`) || contains(ServiceName, \`ec2message\`)].{ServiceName:ServiceName,ServiceType:ServiceType[*].ServiceType}"
[ { "ServiceName": "com.amazonaws.ap-northeast-1.ec2messages", "ServiceType": [ "Interface" ] }, { "ServiceName": "com.amazonaws.ap-northeast-1.ssm", "ServiceType": [ "Interface" ] }, { "ServiceName": "com.amazonaws.ap-northeast-1.ssmmessages", "ServiceType": [ "Interface" ] } ]
エンドポイント追加の前に、VPCのDNSホスト名を有効化する必要があるので、有効化します。
aws ec2 modify-vpc-attribute --enable-dns-hostnames --vpc-id vpc-028bdb0ee3a9213b4
有効化されているか確認します。
aws ec2 describe-vpc-attribute --attribute enableDnsHostnames --vpc-id vpc-028bdb0ee3a9213b4 { "VpcId": "vpc-028bdb0ee3a9213b4", "EnableDnsHostnames": { "Value": true } }
VPCのprivateサブネットに各エンドポイントを作成 (ssm
, ssmmessage
, ec2message
)
aws ec2 create-vpc-endpoint --vpc-id vpc-028bdb0ee3a9213b4 --vpc-endpoint-type Interface --service-name com.amazonaws.ap-northeast-1.ssm --subnet-id subnet-03e945e9c28079b4f --security-group-id sg-0f43c64ef09c225d7
aws ec2 create-vpc-endpoint --vpc-id vpc-028bdb0ee3a9213b4 --vpc-endpoint-type Interface --service-name com.amazonaws.ap-northeast-1.ssmmessages --subnet-id subnet-03e945e9c28079b4f --security-group-id sg-0f43c64ef09c225d7
aws ec2 create-vpc-endpoint --vpc-id vpc-028bdb0ee3a9213b4 --vpc-endpoint-type Interface --service-name com.amazonaws.ap-northeast-1.ec2messages --subnet-id subnet-03e945e9c28079b4f --security-group-id sg-0f43c64ef09c225d7
EC2を起動後、しばらく経ってからssmで、インスタンス情報が取得できればOKです。
aws ec2 start-instances --instance-id i-03c71fcc4ef8e6b20 aws ssm describe-instance-information
あとはローカルの ~/.ssh/config
に SSHセッション設定を記載します。
(AWS CLIで使用しているAWSプロファイル名は、適宜変更してください)
Host gcp-vpn-test-kasahara ProxyCommand sh -c "aws ssm start-session --target i-03c71fcc4ef8e6b20 --document-name AWS-StartSSHSession --parameters 'portNumber=%p' --region ap-northeast-1 --profile <AWSプロファイル名>" User ec2-user IdentityFile ~/.ssh/gcp-vpn-test-kasahara/gcp-vpn-test-kasahara.pem
SSHでEC2にログインできればOKです。
ssh gcp-vpn-test-kasahara
一旦ログアウトして、EC2を停止しておきます。
aws ec2 stop-instances --instance-id i-03c71fcc4ef8e6b20
gcloudコマンドインストール (with NATゲートウェイの導入)
確認用に bq
コマンドを使えるようにします。
gcloud
コマンドをインストールすると、 bq
コマンドも使えるようになります。
ただ、 gcloud
コマンドインストール時にインターネット接続が必要なので、今回は一時的にNATゲートウェイを導入してプライベートサブネットからインターネット接続できるようにします。
NATゲートウェイ用のElastic IPを取得
aws ec2 allocate-address #=> AllocationId: eipalloc-0d7457f38318f3690
NATゲートウェイの作成
NATゲートウェイはパブリックサブネットに作成します。
aws ec2 create-nat-gateway --subnet-id subnet-054f3f50f4e3047e8 --allocation-id eipalloc-0d7457f38318f3690 #=> NatGatewayId: nat-0634c1ebc49a7feca
プライベートサブネットで使用しているルートテーブルに、NAT Gatewayへの経路を追加します。
aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-028bdb0ee3a9213b4 #=> RouteTableId: rtb-0bc6e62228e1012cb #=> コマンド実行結果から、VPC(10.128.0.0/20)へのルーティングしか設定していないルートテーブルのIDを参照する aws ec2 create-route --route-table-id rtb-0bc6e62228e1012cb --destination-cidr-block 0.0.0.0/0 --nat-gateway-id nat-0634c1ebc49a7feca
これでプライベートサブネット上のEC2もインターネットアクセス可能になったので、 EC2インスタンスを起動してからSSHログインしてgcloudインストールします。
aws ec2 start-instances --instance-id i-03c71fcc4ef8e6b20 ssh gcp-vpn-test-kasahara
## EC2上での実行 curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-359.0.0-linux-x86_64.tar.gz tar xvf google-cloud-sdk-359.0.0-linux-x86_64.tar.gz ./google-cloud-sdk/install.sh ./google-cloud-sdk/bin/gcloud init
インストールが終了したら、NAT Gatewayは削除しておきます。
## ローカルマシン上で実行 aws ec2 delete-nat-gateway --nat-gateway-id nat-0634c1ebc49a7feca
NAT Gatewayで使用したElastic IPの解放します。
aws ec2 release-address --allocation-id eipalloc-0d7457f38318f3690
プライベートサブネットのルーティングを修正します。 (NAT Gatewayへの経路を削除)
aws ec2 delete-route --route-table-id rtb-0bc6e62228e1012cb --destination-cidr-block 0.0.0.0/0
以上で、AWS側の準備は完了です。
GCP設定
私がGCPに慣れていないため、こちらはマネジメントコンソール上の操作内容を掲載しております。設定時に gcloud
コマンドの内容が取得できるので、参考までに掲載しております。
VPC / Subnet
左側メニューの [ネットワーキング] ⇒ [VPCネットワーク] ⇒ [VPCネットワーク] へ。 Compute Engine APIがまだ有効化されていない場合は、有効にしておきます。
「VPCネットワークを作成」をクリックします。
今回は、VPC内のサブネットは東京リージョンのみ1つだけ作成します。
- VPC名: aws-vpn-test-vpc
- VPC説明: vpc for aws-vpn-test
- サブネット:
- カスタム
- 新しいサブネット
- サブネット名: aws-vpn-test-asne1-subnet-1
- サブネット説明: subnet on asia-northeast1 for aws-vpn-test
- リージョン: asia-northeast1
- IPアドレス範囲: 10.146.0.0/24
- 限定公開のGoogleアクセス: オン
- フローログ: オフ
- 「完了」をクリック
- 動的ルーティングモード: グローバル
- 最大伝送単位 (MTU): 1460 (default)
同等の gcloud
コマンドは以下の通りです。プロジェクト名は適宜変更ください。
gcloud compute networks create aws-vpn-test-vpc --project=<プロジェクト名> --description=vpc\ for\ aws-vpn-test --subnet-mode=custom --mtu=1460 --bgp-routing-mode=global gcloud compute networks subnets create aws-vpn-test-asne1-subnet-1 --project=<プロジェクト名> --description=subnet\ on\ asia-northeast1\ for\ aws-vpn-test --range=10.146.0.0/24 --network=aws-vpn-test-vpc --region=asia-northeast1 --enable-private-ip-google-access
以下のように一覧にVPCが作成できればOKです。
ファイアウォールルール作成
VMインスタンスに対してコンソール上でSSHを行うために、以下のファイアウォールルールを作成します。 Identity-Aware Proxy(35.235.240.0/20)に対して、SSH(tcp:22)を許可します。
[VPCネットワーキング] ⇒ [ファイアウォール]にて、「ファイアウォールルールを作成」をクリックします。
- ファイアウォールルール名: aws-vpn-test-allow-iap
- ログ: オフ (default)
- ネットワーク: aws-vpn-test-vpc
- 優先度: 1000
- トラフィックの方向: 上り
- 一致したときのアクション: 許可
- ターゲット: ネットワーク上のすべてのインスタンス
- ソースフィルタ: IP範囲
- ソースIPの範囲: 35.235.240.0/20
- プロトコルとポート: 指定したプロトコルとポート
- tcp: 22
gcloud compute --project=<プロジェクト名> firewall-rules create aws-vpn-test-allow-iap --direction=INGRESS --priority=1000 --network=aws-vpn-test-vpc --action=ALLOW --rules=tcp:22 --source-ranges=35.235.240.0/20
VMインスタンス作成
[コンピューティング] ⇒ [Compute Engine] ⇒ [VMインスタンス] へ遷移し、「インスタンスを作成」をクリックします。
- インスタンス名: aws-vpn-test-instance-1
- リージョン: asia-northeast1
- ゾーン: asia-northeast1-a
- シリーズ: E2
- マシンタイプ: e2-micro (2 vCPU / 1 GB メモリ)
- サービスアカウント: Compute Engine default service account
- アクセススコープ: デフォルトのアクセス権を許可
- ネットワーキング:
- ネットワークインターフェース:
- ネットワーク: aws-vpn-test-vpc
- サブネットワーク: aws-vpn-test-asne1-subnet-1
- プライマリ内部IP: エフェメラル (自動)
- 外部IP: エフェメラル
- 「完了」をクリック
- ネットワークインターフェース:
他はデフォルト設定でOKです。
ネットワーキングは省略すると default VPCに設置されます。今回は作成したVPC/Subnetを明示的に指定してあげないと、VPN接続時の疎通確認に失敗します。
gcloud compute instances create aws-vpn-test-instance-1 --project=<プロジェクト名> --zone=asia-northeast1-a --machine-type=e2-micro --network-interface=network-tier=PREMIUM,subnet=aws-vpn-test-asne1-subnet-1 --maintenance-policy=MIGRATE --service-account=<サービスアカウント名> #...省略...
VMインスタンスが起動できたら、コンソール上の「SSH」をクリックします。ブラウザ上でSSHログインできます。
以降の作業で nslookup
を使用するので、SSHログインしてインストールしておきます。
## VMインスタンス上で実行 sudo apt-get install dnsutils
以上で、GCP側環境の準備ができました。
まとめ
今回はCLIベースでの構築ができるようにAWS/GCPでCLIコマンドを用意しました。
Webコンソール上での操作やCfn/CDKなどのツールに慣れている方は適宜読み替えていただければと思います。次はVPN接続設定作業を行います。